# encoding=utf8
# noinspection PyBroadException
import sys
import datetime
import os
import subprocess
from flask import Flask, render_template, request, redirect, url_for, json, jsonify
from flask_cors import CORS
from modes import db, Hosts, projects, DeployTask, Node, Logs
from gitclone import git
# from repo import GitRepository
from utils import Codezip
from sqlalchemy import or_, and_
from sshclient import SSHProxy
from flask_socketio import SocketIO, emit
from sshclient import SSHProxy

# sys.setdefaultencoding('utf-8')
# reload(sys)


app = Flask(__name__)
db.init_app(app)
CORS(app)
socketio = SocketIO()
# socketio.init_app(app,cors_allowed_origins.'*')
socketio.init_app(app)
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/smartssh'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
date = datetime.datetime.now().strftime('%Y%m%d%H')
socketio = SocketIO()
socketio.init_app(app, cors_allowed_origins='*')
name_space = '/dcenter'


@app.route('/push')
def push_once():
    event_name = 'dcenter'
    broadcasted_data = {'data': "test message!"}
    socketio.emit(event_name, broadcasted_data, broadcast=False, namespace=name_space)
    return 'done!'


@socketio.on('my_event', namespace=name_space)
def mtest_message(message):
    print(message)
    emit('my_response',
         {'data': message['data'], 'count': 1})


@app.route('/')
def hello_world():
    db.create_all()
    return render_template('server.html')


@app.route('/list')
def list():
    hostlist = Hosts.query.all()
    print(hostlist)
    return render_template('server.html', hostlist=hostlist)


@app.route('/status/<int:id>', methods=['GET', 'POST'])
def status(id):
    if request.method == "GET":
        print(id)
        taskstatus = DeployTask.query.filter_by(id=id).first()  # 找到发布信息
        uid = taskstatus.uid
        nodeinfo = Node.query.filter_by(task=uid).all()
        statulist = []
        for row in nodeinfo:
            nostatus = {'key': str(row.id), "parent": str(row.parent), 'text': str(row.text), 'color': str(row.status)}
            statulist.append(nostatus)
        return jsonify(statulist)
    else:
        taskstatus = DeployTask.query.filter_by(id=id).first()  # 找到发布信息
        return json.dumps({'code': 'init', 'data': status})


@app.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'GET':
        return render_template('addserver.html')
    else:
        dic1 = request.form
        # savehost(dic1)
        return redirect(url_for('list'))


@app.route('/project', methods=['GET', 'POST'])
def project():
    if request.method == 'GET':
        pallroject = projects.query.all()
        return render_template('project.html', pallroject=pallroject)
    else:
        dic2 = request.form
        project(dic2)
        return redirect(url_for('project'))


# 根据ID号获取项目的信息
@app.route('/task/<int:id>', methods=['GET', 'POST'])
def task(id):
    if request.method == 'GET':
        project = projects.query.filter_by(id=id).first()  # 根据项目ID拿到项目信息
        tasklist = DeployTask.query.filter_by(project=project.project).all()  # 拿到此项目的发布信息
        return render_template('tasklist.html', tasklist=tasklist, project=project)
    else:
        dic2 = request.form
        addproject(dic2)
        return redirect(url_for('project'))


# 添加发布任务
@app.route('/addtask/<int:id>', methods=['GET', 'POST'])
def addtask(id):
    if request.method == 'GET':
        projectinfo = projects.query.filter_by(id=id).first()
        return render_template('addtask.html', projectinfo=projectinfo)
    else:
        projectinfo = projects.query.filter_by(id=id).first()
        project = projectinfo.project
        env = projectinfo.env
        dic3 = request.form
        date = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        uid = project + '-' + env + '-' + dic3['tag'] + '-' + date
        addtaskdb(dic3, project, uid)
        return redirect(url_for('project'))


@app.route('/takeinfo/<int:id>', methods=['GET', 'POST'])
def takeinfo(id):
    if request.method == 'GET':
        taskinfo = DeployTask.query.filter_by(id=id).first()
        pro = taskinfo.project
        prinfo = projects.query.filter_by(project=pro).first()
        # git(prinfo.repo, taskinfo.tag)
        return render_template('bak/run.html', taskinfo=taskinfo, prinfo=prinfo)


@app.route('/addproject', methods=['GET', 'POST'])
def addproject():
    if request.method == 'GET':
        return render_template('addpro.html')
    else:
        dic2 = request.form
        project(dic2)
        return redirect(url_for('project'))


@app.route('/get', methods=['GET', 'POST'])
def get():
    if request.method == 'GET':
        return render_template('run.html')


@app.route('/run1', methods=['GET', 'POST'])
def run1():
    if request.method == 'GET':
        with SSHProxy('192.168.64.148', int(22), 'root', '123456') as ssh:
            ssh.command('ls')
            return "run1"


@app.route('/run/<int:id>', methods=['GET', 'POST'])
def run(id):
    if request.method == 'GET':
        taskinfo = DeployTask.query.filter_by(id=id).first()
        taskinfo.status = "发布中"
        db.session.commit()
        projectinfo = projects.query.filter_by(project=taskinfo.project).first()  # 找到相对应的项目信息
        serverpath = '/root/update/' + date + '/' + '%s' % taskinfo.uid  # 服务器目录
        localpath = '/Users/dayang/PycharmProjects/Devops/codes/' + date
        uploadfile = localpath + '/' + taskinfo.uid + '.zip'  # 上传文件的约绝对地扯
        serverfile = serverpath + '/' + taskinfo.uid + '.zip'  # 上传文件的约绝对地扯
        allhost = projects.query.filter_by(project=taskinfo.project).first()
        start = Node(task=taskinfo.uid, text='开始', status='green')
        db.session.add(start)
        db.session.commit()
        if projectinfo.zip == "on":
            print("需要编译")
            return "zip"
        else:
            downloadstatus = "green"
            # 下载代码并打包
            try:
                git(projectinfo, taskinfo)
                # 添加下载节点
                startid = Node.query.filter_by(task=taskinfo.uid, text='开始').first()
                startdownload = Node(task=taskinfo.uid, text='下载编译打包', status=downloadstatus, parent=startid.id)
                db.session.add(startdownload)
                db.session.commit()
                startdownloadid = Node.query.filter_by(task=taskinfo.uid, text='下载编译打包').first()
                fileupload = Node(task=taskinfo.uid, text='文件上传', parent=startdownloadid.id, status=downloadstatus)
                db.session.add(fileupload)
                db.session.commit()
                try:  # 下载后执行的脚本 ,打包编译
                    os.system("pwd")
                except Exception as e:
                    logtypes = 0
                    createlogs(uid=taskinfo.uid, types=logtypes, result=e)
                    return "下载后执行失败"
            except Exception as e:  # 如果下载出错
                logtypes = 0
                createlogs(uid=taskinfo.uid, types=logtypes, result=e)
                downloadstatus = "red"
                startdownload = Node(task=taskinfo.uid, text='下载编译打包', status=downloadstatus, parent=start.id)
                fileupload = Node(task=taskinfo.uid, text='文件上传', parent=startdownloadid.id)
                db.session.add(startdownload)
                db.session.commit()
                db.session.add(fileupload)
                db.session.commit()
                return "下载出错"
            else:
                print("开始上传")
                allhost = projects.query.filter_by(project=taskinfo.project).first()
                serverslist = allhost.servers.split(",")
                uploadfilenode = Node.query.filter_by(task=taskinfo.uid, text='文件上传').first()
                upstatus = "green"
                for host in serverslist:
                    infohost = Hosts.query.filter_by(hostname=host).first()
                    try:
                        with SSHProxy(infohost.ipaddr, int(infohost.port), infohost.username,
                                      infohost.passwd) as ssh:
                            result = ssh.command('mkdir -p %s' % serverpath)  # 在服务器上创建文件夹
                            ssh.upload(uploadfile, serverfile)
                            result1 = ssh.command('ls /root')
                            print(result1)
                            # result1 = ssh.command('unzip %s -d %s' % (serverfile, serverpath))  # 解压文件
                            uploadstatus = Node(task=taskinfo.uid, text=infohost.hostname, status=upstatus,
                                                parent=uploadfilenode.id, servers=infohost.hostname)
                            db.session.add(uploadstatus)
                            db.session.commit()
                            print("197-upstatus:%s" % upstatus)
                    except Exception as e:
                        result = e
                        types = 0
                        createlogs(taskinfo.uid, types, result=result)
                        upstatus = "red"
                        uploadstatus = Node(task=taskinfo.uid, text=infohost.hostname, status=upstatus,
                                            parent=uploadfilenode.id, servers=infohost.hostname)
                        db.session.add(uploadstatus)
                        db.session.commit()  # "g更新一下数据库状态"
                        if upstatus == "red":
                            continue
                    return "error"
                return "hello"


def addtaskdb(dic3, project, uid):
    print("line 93 %s" % project)
    addtask1 = DeployTask(uid=uid, project=project, tag=dic3['tag'], versioninfo=dic3['versioninfo'],
                          after_download=dic3['after_download_sc'], before_download=dic3['before_download_sc'],
                          before_deploy_sc=dic3['before_deploy_sc'], after_deploy_sc=dic3['after_deploy_sc'])
    db.session.add(addtask1)
    db.session.commit()


def createlogs(uid, types, result):
    if types == 0:  # 0为系统错误日志
        addlogs = Logs(uid=uid, types=types, result=result)
        db.session.add(addlogs)
        db.session.commit()
    elif types == 1:  # 1为操作日志
        pass


if __name__ == '__main__':
    socketio.run(app, host='127.0.0.1', port=6000)
    # app.run(host='0.0.0.0', port='5000')
